package ru.vsu.amm.fuzzy;

/**
 * Функция квантификации.
 * @author Иванов Илья
 * @sice 05 января 2013
 *
 */
public abstract class Quantifier {

	public abstract double calc(double x);
	
	public double[] getWeightVector(int dim) {
		double[] vector = new double[dim];
		vector[0] = calc(1.0 / (double) dim);
		
		for (int i = 1; i < vector.length; i++)
			vector[i] = calc((double) (i + 1) / (double) dim) - calc((double) i / (double) dim);
		
		return vector;
	}
	
	public static double orness(double[] weights) {
		double sum = 0;
		for (int i = 0; i < weights.length - 1; i++)
			sum += weights[i] * (weights.length - i - 1);
		
		return sum / (weights.length - 1);
	}
	
	public static double andness(double[] weights) {
		return 1 - orness(weights);
	}
	
	/**
	 * Почти половина.
	 */
	public static class Half extends Quantifier {
		
		private final int m;
		
		public Half(int objectCount) {
			this.m = objectCount / 2;
		}
		
		public double calc(double x) {
			double barrier = 1.0 / m;
			if (x < barrier)
				return m * x;
			
			return 1;
		}
	}
	
	/**
	 * Большинство.
	 * [a, b] нестрого вложен в [0, 1].
	 */
	public static class Majority extends Quantifier {
		
		private final double a;
		private final double b;
		
		public Majority(double a, double b) {
			this.a = a;
			this.b = b;
		}
		
		public double calc(double x) {
			if (x < a)
				return 0;
			
			if (x < b)
				return (x - a) / (b - a);
			
			return 1;
		}
	}
	
	/**
	 * x ^ alpha
	 */
	public static class Power extends Quantifier {
		
		private final double alpha;
		
		public Power(double alpha) {
			this.alpha = alpha;
		}

		public double calc(double x) {
			return Math.exp(alpha * Math.log(x));
		}
	}
}